home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C++ / Frameworks / Sprocket Framework DR2 / Sprocket Framework / SprocketMain.cp < prev    next >
Text File  |  1996-06-15  |  22KB  |  880 lines

  1. /*
  2.  
  3.     File:        SprocketMain.cp
  4.     Project:    Sprocket Framework 1.1 (DR2), released 6/15/96
  5.     Contains:    The “guts” of a Macintosh application.
  6.     To Do:        No known problems or bugs
  7.  
  8.     Sprocket Major Contributors:
  9.     ----------------------------
  10.     Dave Falkenburg, producer of Sprocket 1.0
  11.     Bill Hayden,     producer of Sprocket 1.1
  12.     Steve Sisak,     producer of the upcoming Sprocket 2.0
  13.     
  14.     Pete Alexander        Steve Falkenburg    Randy Thelen
  15.     Eric Berdahl        Nitin Ganatra        Chris K. Thomas
  16.     Marshall Clow        Dave Hershey        Leonard Rosenthal
  17.     Tim Craycroft        Dave Mark            Dean Yu
  18.     David denBoer        Gary Powell
  19.     Cameron Esfahani    Jon Summers            Apple Computer, Inc.
  20.         
  21.     Comments, Additions, or Corrections:
  22.     ------------------------------------
  23.     Bill Hayden, Nikol Software <nikol@codewell.com>
  24.  
  25. */
  26.  
  27.  
  28. #include "Sprocket.h"
  29.  
  30. #include <limits.h>        //    For LONG_MAX
  31.  
  32.  
  33. #ifndef __GESTALT__
  34.     #include <Gestalt.h>
  35. #endif
  36.  
  37. #include <Menus.h>
  38. #include <Devices.h>
  39. #include <DiskInit.h>
  40. #include <Threads.h>
  41. #include <Traps.h>
  42. #include <Speech.h>
  43. #include <SpeechRecognition.h>
  44. #include <AppleGuide.h>
  45.  
  46. #ifndef __CODEFRAGMENTS__
  47.     #include "CodeFragments.h"
  48. #endif
  49.  
  50. #if    qInlineInputAware
  51.     #include <TextServices.h>
  52.     #include <TSMTE.h>
  53. #endif
  54.  
  55. #if    qUseQuickDrawGX
  56.     #include <GXEnvironment.h>
  57.     #include <GXGraphics.h>
  58.     #include <GraphicsLibraries.h>
  59.     #include <GXPrinting.h>
  60.  
  61.     #if    qUseQuickDrawGXDebugging
  62.         #include <GraphicsDebugLibrary.c>
  63.     #endif
  64. #endif
  65.  
  66. #if qUseQC
  67.     #include "QCAPI.h"
  68. #endif
  69.  
  70. #include "StandardMenus.h"
  71. #include "UDialog.h"
  72. #include "Window.h"
  73. #include "SplashWindow.h"
  74. #include "AEHandling.h"
  75. #include "LinkedList.h"
  76.  
  77.  
  78. //    Function Prototypes
  79.  
  80. void    main(void);
  81. void    MainEventLoop(void);
  82.  
  83. void    HandleMouseDown(TWindow * topWindowObj, EventRecord * anEvent);
  84. void    HandleClose(WindowRef aWindow);
  85. void    HandleMenu(TWindow * topWindow, long menuCode);
  86.  
  87.  
  88. //    Globals
  89.  
  90. Boolean                gDone = false;
  91. TMenuBar *            gMenuBar = nil;
  92. TSplashWindow *        gSplashWindow = nil;
  93.  
  94. long                gSystemVersion = 0;
  95. Boolean                gHasColorQuickdraw = false;
  96. Boolean                gHasThreadManager = false;
  97. Boolean                gHasDragManager = false;
  98. Boolean                gHasAppleScript = false;
  99. Boolean                gHasDisplayManager = false;
  100. Boolean                gHasSpeechManager = false;
  101. Boolean                gHasSpeechRecognitionManager = false;
  102. Boolean                gHasAppleGuide = false;
  103.  
  104. #if    qAOCEAware
  105. Boolean                gHasAOCE = false;
  106. #endif
  107.  
  108. #if    qInlineInputAware
  109. Boolean                gHasTextServices = false;
  110. Boolean                gHasTSMTE = false;
  111.  
  112. Boolean                TSMEventWrapperForKotoeri(EventRecord *anEvent);
  113. #endif
  114.  
  115. #if    qUseQuickDrawGX
  116. Boolean                gHasQuickDrawGX = false;
  117. long                gQuickDrawGXVersion = 0;
  118. long                gQuickDrawGXPrintingVersion = 0;
  119. gxGraphicsClient    gQuickDrawGXClient;
  120. #endif
  121.  
  122. GrafPtr                gWindowManagerPort;
  123. Rect                gDeskRectangle;
  124. RgnHandle            gMouseRegion = nil;
  125.  
  126. TLinkedList*        gCommandQueue;
  127.  
  128.  
  129.  
  130.  
  131. //    Values that can be adjusted by other application code to change
  132. //    the behavior of the MainEventLoop.
  133. //
  134. //    Rules of thumb:
  135. //
  136. //        Increase gXXXRunQuantum (and decrease gXXXSleepQuantum) when:
  137. //            The application has many threads running that need time
  138. //
  139. //        Decrease gXXXRunQuantum when:
  140. //            Sending AppleEvents to other applications
  141. //            Launching other applications
  142. //            Running in the background
  143.  
  144. unsigned long    gForegroundRunQuantum = 0;
  145. unsigned long    gForegroundSleepQuantum = GetCaretTime();
  146. unsigned long    gBackgroundRunQuantum = 0;
  147. unsigned long    gBackgroundSleepQuantum = LONG_MAX;
  148.  
  149.  
  150. //    Globals used to “tune” the performance of MainEventLoop
  151. //    (assume we’ll be starting in the foreground)
  152.  
  153. static    unsigned long    gRunQuantum = gForegroundRunQuantum;
  154. static    unsigned long    gSleepQuantum = gForegroundSleepQuantum;
  155.  
  156. #if GENERATINGPOWERPC
  157. #ifndef    __MWERKS__
  158. QDGlobals    qd;
  159. #endif
  160. #endif
  161.  
  162.  
  163.  
  164. /*****************************************************************************/
  165.  
  166.  
  167.  
  168. void main(void)
  169. {
  170.     long        feature;
  171.  
  172.     MaxApplZone();
  173.     MoreMasters();
  174.     MoreMasters();
  175.     MoreMasters();
  176.     MoreMasters();
  177.  
  178.     InitGraf(&qd.thePort);    
  179.     InitFonts();
  180.     InitWindows();
  181.     InitMenus();
  182.     TEInit();
  183.     InitDialogs(nil);
  184.     
  185. #if qUseQC
  186.     if (QCInstalled() == noErr)
  187.         QCActivate(nil);
  188. #endif
  189.  
  190.     if (GetToolTrapAddress(_Unimplemented) == GetOSTrapAddress(_Gestalt))
  191.         ErrorAlert(kCoreErrorStrings, kUnsupportedSystemSoftware, true);
  192.         
  193.     Gestalt(gestaltSystemVersion, &gSystemVersion);
  194.     
  195.     if (Gestalt(gestaltQuickdrawFeatures,&feature) == noErr)
  196.         gHasColorQuickdraw = ((feature & (1 << gestaltHasColor)) != 0);
  197.  
  198.     gSplashWindow = new TSplashWindow;    
  199.  
  200.     //    Check for and Initialize QuickDraw GX early on to avoid heap fragmentation
  201.     
  202. #if    qUseQuickDrawGX
  203.     //    Check for and initialize QuickDrawGX
  204.     if (Gestalt(gestaltGXVersion, &gQuickDrawGXVersion) == noErr)
  205.         {
  206.         if (Gestalt(gestaltGXPrintingMgrVersion, &gQuickDrawGXPrintingVersion) == noErr)
  207.             {
  208. #if GENERATINGCFM
  209.             if ((Ptr) GXEnterGraphics != (Ptr) kUnresolvedCFragSymbolAddress)
  210. #endif
  211.             gHasQuickDrawGX = true;
  212.             }
  213.         }
  214.  
  215.     if (gHasQuickDrawGX)
  216.         {
  217.         // Initialize the graphics and printing environments.
  218.         //    For additional details see "IM: QD GX Environment & Utilities."
  219.         
  220.         //    We let QuickDraw GX look for a resource  of type 'gasz' with an ID of 0.
  221.         //    GX uses the first long word of that resource as the graphics heap size.
  222.         //    To determine the memory requirements of your graphics client heap see:
  223.         //    “IM: QD GX Environment & Utilities pp2-8,2-9”
  224.         
  225.         //    NOTE:    If your application does not provide this resource,
  226.         //            QuickDraw GX version 1.0 uses a default size of 600 KB.
  227.  
  228.         gQuickDrawGXClient = GXNewGraphicsClient(nil, kUseGraphicsSizeResource, kAllowGXToExtendGraphicsHeap);
  229.         if (gQuickDrawGXClient)
  230.             {
  231.             //    NOTE:    GXNewGraphicsClient() does not allocate memory to the heap
  232.             //            until GXEnterGraphics()    is called, so go ahead and call it now
  233.             //            while we have a chance to deal with things nicely.
  234.             //
  235.             // NOTE:    GXEnterGraphics() should only fail if there is not enough memory. 
  236.             
  237.             GXEnterGraphics();
  238.  
  239.             if (GXGetGraphicsError(nil) == noErr)
  240.                 {
  241. #if    qUseQuickDrawGXDebugging
  242.                 // If qUseQuickDrawGXDebugging = true, enable on GX Validation and graphics library errors & notices.
  243.  
  244.                 //    NOTES from Jon Summers:
  245.                 //    As you increase the amount of validation, drawing speed will SLOW
  246.                 //    down due to all of the internal checking. Also, if you play with
  247.                 //    settings enough validation seems to become inconsistent
  248.  
  249.                 GXSetValidation(    //    gxInternalValidation    |
  250.                                     //    gxAllObjectValidation    |
  251.                                     //    gxApHeapValidation        |
  252.                                         gxPublicValidation);        // check parameters to public routines
  253.  
  254.                 //    This functionality will only work with the "debugging" version of QuickDraw GX.
  255.                 //    If you don't have the debugging version installed, these functions will not work. 
  256.  
  257.                 SetGraphicsLibraryErrors();
  258.                 SetGraphicsLibraryNotices();    
  259. #endif
  260.                 if (GXInitPrinting() != noErr)        // See IM: QuickDraw GX Printing
  261.                     {
  262.                     //    We couldn’t initialize printing, so clean up pretend GX isn’t around
  263.                     //    ••• For safety’s sake, we’ll probably want to bail here.
  264.                     
  265.                     if (gQuickDrawGXClient)
  266.                         GXDisposeGraphicsClient(gQuickDrawGXClient);
  267.                     gHasQuickDrawGX = false;
  268.                     }
  269.                 }
  270.             }
  271.         }
  272.  
  273.     //if (gQuickDrawGXClient)
  274.         //InitCommonColors();        // Initialize the CommonColors Library.
  275. #if    qRequireQuickDrawGX
  276.     else
  277.         ErrorAlert(kCoreErrorStrings, kNeedsQuickdrawGX, false);
  278. #endif    //    qRequireQuickDrawGX
  279. #endif    //    qUseQuickDrawGX
  280.  
  281.  
  282.     if ((Gestalt(gestaltAppleEventsAttr,&feature) == noErr) &&
  283.         (feature & (1 << gestaltAppleEventsPresent)))
  284.         {
  285.         //    Figure out if we need to do AppleEvent recording
  286.         gHasAppleScript = ((feature & (1 << gestaltScriptingSupport)) != 0);
  287.         }
  288.     else
  289.         ErrorAlert(kCoreErrorStrings, kUnsupportedSystemSoftware, true);
  290.         
  291.     if ((Gestalt(gestaltHelpMgrAttr, &feature) == noErr) && (feature & (1 << gestaltAppleGuidePresent)))
  292.         {
  293.         gHasAppleGuide = true;
  294.         }
  295.  
  296. #if    qInlineInputAware
  297.     if ((Gestalt(gestaltTSMgrVersion,&feature) == noErr) && (feature >= 1))
  298.         {
  299.         gHasTextServices = true;
  300.         if (Gestalt(gestaltTSMTEAttr, &feature) == noErr)
  301.             gHasTSMTE = (feature & (1 << gestaltTSMTEPresent));
  302.  
  303.         if (InitTSMAwareApplication() != noErr)
  304.             {
  305.             gHasTextServices = false;
  306.             gHasTSMTE = false;
  307.             }
  308.         }
  309. #endif
  310.  
  311.     if (Gestalt(gestaltThreadMgrAttr,&feature) == noErr)
  312.         {
  313. #if GENERATINGCFM
  314.         //    If running under the CFM, make sure that we not only have the
  315.         //    Thread Manager, but also the shared library, too.
  316.         //    Because of the wonders of weak linking and out of memory errors
  317.         //    we need to also check to make sure that an entrypoint in the library
  318.         //    is there, too. 
  319.         if ((Ptr) NewThread != (Ptr) kUnresolvedCFragSymbolAddress)
  320.             gHasThreadManager = ((feature & ((1 << gestaltThreadMgrPresent) | (1 << gestaltThreadsLibraryPresent))) != 0);
  321. #else
  322.         gHasThreadManager = ((feature & (1 << gestaltThreadMgrPresent)) != 0);
  323. #endif
  324.         }
  325.  
  326. #if    qRequireThreadManager
  327.     if (gHasThreadManager == false)
  328.         ErrorAlert(kCoreErrorStrings, kNeedsThreadManager, true);
  329. #endif
  330.  
  331.     //    Check for and install Drag Manager callbacks
  332.     if (Gestalt(gestaltDragMgrAttr,&feature) == noErr)
  333.         {
  334. #if GENERATINGCFM
  335.         //    If running under the CFM, make sure that we not only have the
  336.         //    Thread Manager, but also the shared library, too.
  337.         if ((Ptr) NewDrag != (Ptr) kUnresolvedCFragSymbolAddress)
  338.             gHasDragManager = ((feature & ((1 << gestaltDragMgrPresent) | (1 << gestaltPPCDragLibPresent))) != 0);
  339. #else
  340.         gHasDragManager = ((feature & (1 << gestaltDragMgrPresent)) != 0);
  341. #endif
  342.  
  343.         if (gHasDragManager)
  344.             {
  345.             InstallTrackingHandler(NewDragTrackingHandlerProc(CallWindowDragTrackingHandler),(GrafPtr) nil,nil);
  346.             InstallReceiveHandler(NewDragReceiveHandlerProc(CallWindowDragReceiveHandler),(GrafPtr) nil,nil);
  347.             }
  348.         }
  349.  
  350.     //    Check for Display Manager
  351.     if (Gestalt(gestaltDisplayMgrAttr,&feature) == noErr)
  352.         gHasDisplayManager = ((feature & (1 << gestaltDisplayMgrPresent)) != 0);
  353.  
  354. #if    qAOCEAware && qPowerTalkSystemSupport
  355.     //    Check for and initialize AOCE Standard Mail package if it exists
  356.     if ((Gestalt(gestaltSMPMailerVersion,&feature) == noErr) && (feature != 0))
  357.         {
  358. #if GENERATINGCFM
  359.         if ((Ptr) SMPInitMailer != (Ptr) kUnresolvedCFragSymbolAddress)
  360.             gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  361. #else
  362.         gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  363. #endif
  364.         }
  365. #endif
  366.  
  367.     // Check for and initialize the Speech Manager
  368.     if ((Gestalt(gestaltSpeechAttr, &feature) == noErr) && (feature != 0))
  369.         {
  370. #if GENERATINGCFM
  371.         //    If running under the CFM, make sure that we not only have the
  372.         //    Speech Manager, but also the shared library, too.
  373.         //    Because of the wonders of weak linking and out of memory errors
  374.         //    we need to also check to make sure there is an entrypoint in the library, too. 
  375.         if ((Ptr) CountVoices != (Ptr) kUnresolvedCFragSymbolAddress)
  376.             gHasSpeechManager = ((feature & ((1 << gestaltSpeechMgrPresent) | (1 << gestaltSpeechHasPPCGlue))) != 0);
  377. #else
  378.         gHasSpeechManager = ((feature & (1 << gestaltSpeechMgrPresent)) != 0);
  379. #endif
  380.         }
  381.  
  382.     // Check for and initialize the Speech Manager
  383.     if ((Gestalt(gestaltSpeechRecognitionVersion, &feature) == noErr) && (feature != 0))
  384.         {
  385. #if GENERATINGCFM
  386.         //    If running under the CFM, make sure that we not only have the
  387.         //    Speech Recognition Manager, but also the shared library, too.
  388.         //    Because of the wonders of weak linking and out of memory errors
  389.         //    we need to also check to make sure there is an entrypoint in the library, too.
  390.         //    We need version 1.5 or later to use the new API (a pre-release version is fine).
  391.         if ((Ptr) SROpenRecognitionSystem != (Ptr) kUnresolvedCFragSymbolAddress)
  392.             {
  393.             if (feature >= 0x00000150)
  394.                 gHasSpeechRecognitionManager = true;
  395.             }
  396. #else
  397.         if (feature >= 0x00000150)
  398.             gHasSpeechRecognitionManager = true;
  399. #endif
  400.         }
  401.  
  402.     //    Initialize our AppleEvent Handling Routines
  403.     InitAppleEventRoutines();
  404.  
  405.     //    Setup desktop rectangle for dragging windows around            
  406.     GetWMgrPort(&gWindowManagerPort);
  407.     gDeskRectangle = (**GetGrayRgn()).rgnBBox;
  408.  
  409.     //    Setup the default menubar
  410.     //        First, create a TMenuBar so we can register commands
  411.     gMenuBar = new TMenuBar();
  412.  
  413.     //        Add the Macintosh menus via an MBAR resource
  414.     gMenuBar->GetNewMenuBar(rMenuBar);
  415.     
  416.     //        add AppleMenu items
  417.     AppendResMenu(GetMenuHandle(mApple), 'DRVR');
  418.  
  419.     //        …and add fonts to the font menu (if it is installed)
  420.     if (GetMenuHandle(mFont))
  421.         AppendResMenu(GetMenuHandle(mFont), 'FONT');
  422.  
  423.     gCommandQueue = new TLinkedList;
  424.     
  425.     OSErr    err = SetupApplication();
  426.     
  427.     delete gSplashWindow;    //    get rid of the splash screen
  428.     
  429.     if (err == noErr)
  430.         {
  431.         MainEventLoop();
  432.         }
  433.  
  434.     TearDownApplication();
  435.  
  436. #if    qInlineInputAware
  437.     if (gHasTextServices)
  438.         (void) CloseTSMAwareApplication();
  439. #endif
  440.         
  441. #if    qUseQuickDrawGX
  442.     //    Tear down QuickDrawGX
  443.     if (gHasQuickDrawGX && gQuickDrawGXClient)
  444.         {
  445.         //DisposeCommonColors();
  446.         GXExitPrinting();        // Close the new printing mgr. 
  447.         GXExitGraphics();        // Deallocate all of the default structures
  448.         GXDisposeGraphicsClient(gQuickDrawGXClient);    
  449.         }
  450. #endif
  451.  
  452.     if (gCommandQueue)
  453.         delete gCommandQueue;
  454.  
  455. #if qUseQC
  456.     QCDeactivate();
  457. #endif
  458. }
  459.  
  460.  
  461.  
  462. /*****************************************************************************/
  463.  
  464.  
  465.  
  466. void MainEventLoop(void)
  467. {
  468.     EventRecord        anEvent;
  469.     unsigned long    nextTimeToCheckForEvents = 0;
  470.     
  471.     while (!gDone)
  472.         {
  473.         gMenuBar->RedrawIfNeeded();
  474.  
  475.         if (gHasThreadManager)
  476.             YieldToAnyThread();
  477.  
  478.         if ((gRunQuantum == 0) ||
  479.             (TickCount() > nextTimeToCheckForEvents))
  480.             {
  481.             nextTimeToCheckForEvents = TickCount() + gRunQuantum;
  482.             
  483.             (void) WaitNextEvent(everyEvent,&anEvent,gSleepQuantum,gMouseRegion);
  484.                         
  485. #if    qInlineInputAware
  486.             if (gHasTextServices && TSMEventWrapperForKotoeri(&anEvent))
  487.                 {
  488.                 }
  489.             else
  490. #endif
  491.                 HandleEvent(&anEvent);
  492.             }
  493.         }
  494.     }
  495.  
  496.  
  497.  
  498. /*****************************************************************************/
  499.  
  500.  
  501.  
  502. #if    qInlineInputAware
  503.  
  504. Boolean TSMEventWrapperForKotoeri(EventRecord *anEvent)
  505. {
  506.     short        oldFont;
  507.     ScriptCode    keyboardScript;
  508.     Boolean        didTSMHandleTheEvent = false;
  509.  
  510.     //    This snippet of code is from TE 27: Inline Input & TextEdit
  511.     //    and is related to working around a bug in Kotoeri, one of the
  512.     //    Japanese Input methods when operating in a mixed script
  513.     //    environment (e.g., Japanese Language Kit)
  514.     
  515.     // make sure we have a port and it's not the Window Manager port
  516.     if (qd.thePort != nil)
  517.         {
  518.         oldFont            = qd.thePort->txFont;
  519.         keyboardScript    = GetScriptManagerVariable(smKeyScript);
  520.  
  521.         if (FontToScript(oldFont) != keyboardScript)
  522.             TextFont(GetScriptVariable(keyboardScript, smScriptAppFond));
  523.         }
  524.  
  525.     didTSMHandleTheEvent = TSMEvent(anEvent);
  526.     
  527.     TextFont(oldFont);        //    restore the font, even though the sample code didn’t
  528.  
  529.     return didTSMHandleTheEvent;
  530. }
  531.  
  532. #endif    
  533.  
  534.  
  535.  
  536. /*****************************************************************************/
  537.  
  538.  
  539.  
  540. void HandleEvent(EventRecord *anEvent)
  541. {
  542.     TWindow    * frontWindowObj;
  543.     
  544.     if (anEvent->what != updateEvt)
  545.         frontWindowObj = GetWindowObject(FrontNonFloatingWindow());
  546.     else
  547.         frontWindowObj = GetWindowObject((WindowRef) anEvent->message);
  548.  
  549.     if (frontWindowObj != nil)
  550. #if    qInlineInputAware
  551.         // give text services a chance to set the cursor shape
  552.         if (gHasTextServices && SetTSMCursor(anEvent->where))
  553.             ;    // do nothing, TSM did it for me
  554.         else    
  555. #endif
  556.             frontWindowObj->AdjustCursor(anEvent);
  557.     
  558.     if ((frontWindowObj != nil) && frontWindowObj->EventFilter(anEvent))
  559.         return;
  560.         
  561.     else switch (anEvent->what)
  562.         {
  563.         case    nullEvent:
  564.             if (frontWindowObj != nil)
  565.                 {
  566.                 frontWindowObj->Idle(anEvent);
  567.                 }
  568.                 
  569.             if (gCommandQueue)
  570.                 {
  571.                 CommandID aCommand = (CommandID)gCommandQueue->GetNthLinkObject(1);
  572.                 if (aCommand != 0)
  573.                     {
  574.                     if (frontWindowObj == nil)                // No front window?  Give it to the app.
  575.                         HandleCommand(aCommand);
  576.                     else if (!frontWindowObj->DoCommand(aCommand))    // Give the front window a crack,
  577.                         HandleCommand(aCommand);        // then the app itself
  578.                         
  579.                     gCommandQueue->FindAndDeleteLink((void *)aCommand);
  580.                     }
  581.                 }
  582.             break;
  583.             
  584.         case    mouseDown:
  585.             HandleMouseDown(frontWindowObj,anEvent);
  586.             break;
  587.         
  588.         case    keyDown:
  589.         case    autoKey:
  590.             if (anEvent->modifiers & cmdKey)
  591.                 {
  592.                 if (frontWindowObj != nil)
  593.                     frontWindowObj->AdjustMenusBeforeMenuSelection();
  594.  
  595.                 long    menuResult = MenuKey((short) anEvent->message & charCodeMask);
  596. #if    qInlineInputAware
  597.                 if (!(gHasTextServices && TSMMenuSelect(menuResult)))
  598. #endif
  599.                     HandleMenu(frontWindowObj,menuResult);
  600.                 HiliteMenu(0);
  601.                 }
  602.             else if (frontWindowObj != nil)
  603.                 frontWindowObj->KeyDown(anEvent);
  604.             break;
  605.             
  606.         case    updateEvt:
  607.             {
  608.             GrafPtr        oldPort;
  609.             WindowRef    aWindow = (WindowRef) anEvent->message;    
  610.                 
  611.             GetPort(&oldPort);
  612.             SetPortWindowPort(aWindow);
  613.             BeginUpdate(aWindow);
  614.             if (frontWindowObj != nil)
  615.                 frontWindowObj->Draw();
  616.             EndUpdate(aWindow);
  617.             SetPort(oldPort);
  618.             }
  619.             break;
  620.             
  621.         case diskEvt:
  622.             if (anEvent->message >> 16)
  623.                 {
  624.                 static    Point    where = {50,50};
  625.                 (void) DIBadMount(where, anEvent->message);
  626.                 }
  627.             break;
  628.                 
  629.         case    osEvt:
  630.             switch ((anEvent->message & osEvtMessageMask) >> 24)
  631.                 {
  632.                 case    mouseMovedMessage:
  633.                     break;
  634.                     
  635.                 case    suspendResumeMessage:                    
  636.  
  637.                     SuspendResumeWindows((anEvent->message & resumeFlag) != 0);
  638.  
  639.                     if (anEvent->message & resumeFlag)
  640.                         {
  641.                         if (anEvent->message & convertClipboardFlag)
  642.                             ReadLocalClipboardFromScrap();
  643.  
  644.                         gRunQuantum = gForegroundRunQuantum;
  645.                         gSleepQuantum = gForegroundSleepQuantum;
  646.                         }
  647.                     else
  648.                         {
  649.                         if (anEvent->message & convertClipboardFlag)
  650.                             WriteLocalClipboardToScrap();
  651.                         gRunQuantum = gBackgroundRunQuantum;
  652.                         gSleepQuantum = gBackgroundSleepQuantum;
  653.                         }
  654.  
  655.                     break;
  656.                 }
  657.             break;
  658.         
  659.         case    kHighLevelEvent:
  660.             (void) AEProcessAppleEvent(anEvent);
  661.             break;
  662.             
  663.         default:
  664.             break;
  665.         }
  666. }
  667.  
  668.  
  669.  
  670. /*****************************************************************************/
  671.  
  672.  
  673.  
  674. void HandleMouseDown(TWindow * topWindowObj,EventRecord *anEvent)
  675. {
  676.     WindowRef    aWindow;
  677.     TWindow        *frontWindowObj;
  678.     short        partCode;
  679.  
  680.     partCode = FindWindow(anEvent->where, &aWindow);
  681.     frontWindowObj = GetWindowObject(aWindow);
  682.     switch(partCode)
  683.         {
  684.         case    inMenuBar:
  685.             //    Thanks mclow! FindWindow made aWindow NULL when inMenuBar!
  686.             frontWindowObj = GetWindowObject(FrontNonFloatingWindow());
  687.             if (frontWindowObj != nil)
  688.                 frontWindowObj->AdjustMenusBeforeMenuSelection();
  689.  
  690.             long    menuResult = MenuSelect(anEvent->where);
  691. #if    qInlineInputAware
  692.             if (!(gHasTextServices && TSMMenuSelect(menuResult)))
  693. #endif
  694.                 HandleMenu(topWindowObj, menuResult);
  695.             HiliteMenu(0);
  696.             break;
  697.             
  698.         case    inSysWindow:
  699.             SystemClick(anEvent, aWindow);
  700.             break;
  701.             
  702.         case    inContent:
  703.             if (frontWindowObj != nil)
  704.                 {
  705.                 GrafPtr    oldPort;
  706.                 
  707.                 GetPort(&oldPort);
  708.                 SetPortWindowPort(aWindow);
  709.                 GlobalToLocal(&anEvent->where);
  710.                 frontWindowObj->ClickAndDrag(anEvent);
  711.                 SetPortWindowPort(aWindow);
  712.                 }
  713.             break;
  714.             
  715.         case    inDrag:
  716.             if (frontWindowObj)
  717.                 frontWindowObj->Drag(anEvent->where);
  718.             break;
  719.             
  720.         case    inGrow:
  721.             if (frontWindowObj)
  722.                 frontWindowObj->Grow(anEvent->where);
  723.             break;
  724.             
  725.         case    inGoAway:
  726.             if (TrackGoAway(aWindow,anEvent->where))
  727.                 HandleClose(aWindow);
  728.             break;
  729.  
  730.         case    inZoomIn:
  731.         case    inZoomOut:
  732.             if (TrackBox(aWindow,anEvent->where,partCode) && (frontWindowObj))
  733.                 frontWindowObj->Zoom(partCode);
  734.             break;
  735.             
  736.         default:
  737.             break;
  738.         }
  739. }
  740.     
  741.  
  742. /*****************************************************************************/
  743.  
  744.  
  745.  
  746. void HandleClose(WindowRef aWindow)
  747. {
  748.     short    windowKind;
  749.     TWindow    *frontWindowObj;
  750.     
  751.     if (aWindow)
  752.         {
  753.         windowKind = GetWindowKind(aWindow);
  754.         if (windowKind < 0)
  755.             {
  756.             CloseDeskAcc(GetWindowKind(aWindow));
  757.             }
  758.         else if ( ((frontWindowObj = GetWindowObject(aWindow)) != nil) &&
  759.                     frontWindowObj->CanClose(false) &&
  760.                     frontWindowObj->Close() &&
  761.                     frontWindowObj->DeleteAfterClose() )
  762.             {
  763.             delete frontWindowObj;
  764.             }
  765.         }
  766. }
  767.  
  768.  
  769.  
  770. /*****************************************************************************/
  771.  
  772.  
  773.  
  774. void HandleMenu(TWindow* topWindow, long menuCode)
  775. {
  776.     short    menu = (short) (menuCode >> 16);
  777.     short    item = (short) (menuCode & 0xffff);
  778.  
  779.         
  780.     //    First, some special case menu handling for Mac OS:    
  781.     //        • Openning “Desk Accessories”
  782.     //        • Passing Edit commands through SystemEdit.
  783.  
  784.     switch (menu)
  785.         {
  786.         case    mApple:
  787.             if (item != iAbout)
  788.                 {
  789.                 Str255    deskAccName;
  790.                 
  791.                 GetMenuItemText(GetMenuHandle(mApple), item, deskAccName);
  792.                 (void) OpenDeskAcc(deskAccName);
  793.                 return;
  794.                 }
  795.             break;
  796.         
  797.         case    mEdit:
  798.             if (SystemEdit(item-1))
  799.                 return;
  800.         
  801.         default:
  802.             break;
  803.         }
  804.  
  805.  
  806.     //    Next, check to see if the menu selection is a command
  807.  
  808.     CommandID    command = gMenuBar->GetCommand(menu, item);
  809.  
  810.     if (command)
  811.         {
  812.         if (command == cQuit)
  813.             {
  814.             TWindow*    frontWindowObj;
  815.             
  816.             frontWindowObj = GetWindowObject(FrontNonFloatingWindow());
  817.             
  818.             while(frontWindowObj != nil)
  819.                 {
  820.                 if (frontWindowObj->CanClose(true) &&
  821.                     frontWindowObj->Close() &&
  822.                     frontWindowObj->DeleteAfterClose() )
  823.                     {
  824.                     delete frontWindowObj;
  825.                     }
  826.                 else
  827.                     return;        // short-circuit the quit command
  828.                     
  829.                 frontWindowObj = GetWindowObject(FrontNonFloatingWindow());
  830.                 }
  831.                 
  832.             gDone = QuitApplication();    // all windows closed, so give the app one final chance
  833.             return;
  834.             }
  835.         
  836.         SendCommandToSelf(command);        // Allow commands to be recorded
  837.         }
  838.     else
  839.         {
  840.         //    If we don’t have a command, give the active window a
  841.         //    chance to handle the raw menu selection.
  842.  
  843.         //    Windows which need to respond to dynamic menus (such as
  844.         //    Font or Windows) menus should use this method.
  845.         
  846.         if (topWindow)
  847.             {
  848.             if (topWindow->DoMenuSelection(menu, item))
  849.                 return;
  850.             }
  851.         
  852.         //    No window wanted to handle the selection, go ahead
  853.         //    and give the application a crack at it.
  854.         
  855.         HandleMenuSelection(menu, item);
  856.         }
  857. }
  858.  
  859.  
  860.  
  861.  
  862. /*****************************************************************************/
  863.  
  864.  
  865.  
  866.  
  867. OSErr    QueueCommand(CommandID    command)
  868. {
  869.     OSErr    err = -1;
  870.     
  871.     if (gCommandQueue && command != 0)
  872.         err = gCommandQueue->CreateAndAddLink((void *)command);    // just storing a CommandID here
  873.     else
  874.         DebugMessage("\pgCommandQueue is nil");
  875.         
  876.     return err;
  877. }
  878.  
  879.  
  880.